﻿using System;
using System.IO;
using System.Text;
using System.Collections.Generic;

using SBPweb.Modules.Modularity;

using SBPweb.MediaCenter.Common.Files;
using SBPweb.MediaCenter.Common.Modularity;
using SBPweb.MediaCenter.Common.Services;

namespace SBPweb.MediaCenter.Modules.Organizer
{

    public abstract class OrganizerServiceBase : ServiceBase, IOrganizerService
    {

        #region Private fields

        private Dictionary<string, IOpenerService> dictOfServices = new Dictionary<string, IOpenerService>();
        private IList<Uri> list = new List<Uri>();
        private int currentIndex;
        private ListRepeatModes repeatMode;
        private string currentExtensionsFilter;

        #endregion

        #region Constructor logic

        public OrganizerServiceBase(IModule parentModule)
            : base(parentModule, "OrganizerService")
        {
        }

        #endregion

        #region Property accessors

        public ListRepeatModes RepeatMode
        {
            get
            {
                return repeatMode;
            }
            set
            {
                repeatMode = value;
            }
        }

        public bool IsPreviousAvailable
        {
            get
            {
                switch (repeatMode)
                {
                    default:
                    case ListRepeatModes.NoRepeat:
                        return currentIndex > 0;
                    case ListRepeatModes.RepeatAll:
                        return true;

                    case ListRepeatModes.RepeatItem:
                        return false;
                }
            }
        }

        public bool IsNextAvailable
        {
            get
            {
                switch (repeatMode)
                {
                    default:
                    case ListRepeatModes.NoRepeat:
                        return currentIndex < list.Count - 1;
                    case ListRepeatModes.RepeatAll:
                        return true;

                    case ListRepeatModes.RepeatItem:
                        return false;
                }
            }
        }

        public virtual string CurrentExtensionsFilter
        {
            get
            {
                return currentExtensionsFilter;
            }
            protected set
            {
                currentExtensionsFilter = value;
            }
        }

        #endregion

        #region Methods

        #region Public functions

        public virtual IList<string> GetSupportedExtensions()
        {
            return new List<string>(dictOfServices.Keys);
        }

        public virtual void Open(Uri uri)
        {
            this.list = GetSiblingUrisIfPossible(uri);
            currentIndex = this.list.IndexOf(uri) - 1;
            OpenNext();
        }

        public virtual void Open(IList<Uri> list)
        {
            this.list = list;
            currentIndex = -1;
            OpenNext();
        }

        public virtual void OpenPrevious()
        {
            StepIndexBack();
            OpenUri(list[currentIndex]);
        }

        public virtual void OpenNext()
        {
            StepIndexForward();
            OpenUri(list[currentIndex]);
        }

        #endregion

        #region Helper functions

        internal void InitializeOpeners()
        {
            foreach (KeyValuePair<string, object> kvp in Module.Host.ModuleLoader.Services)
            {
                IUriOpenerService iuos = kvp.Value as IUriOpenerService;
                if (iuos != null && !(iuos is IOrganizerService))
                {
                    foreach (string ext in iuos.GetSupportedExtensions())
                    {
                        if (!dictOfServices.ContainsKey(ext))
                        {
                            dictOfServices.Add(ext.ToLower(), iuos);
                        }
                    }
                }
            }
            currentExtensionsFilter = FileUriHelper.GetExtensionsFilter(GetSupportedExtensions());
        }

        protected void StepIndexForward()
        {
            switch (repeatMode)
            {
                default:
                case ListRepeatModes.NoRepeat:
                    if (currentIndex < list.Count - 1)
                    {
                        currentIndex++;
                    }
                    break;
                case ListRepeatModes.RepeatAll:
                    currentIndex++;
                    if (currentIndex >= list.Count)
                    {
                        currentIndex = 0;
                    }
                    break;

                case ListRepeatModes.RepeatItem:
                    return;
            }
        }

        protected void StepIndexBack()
        {
            switch (repeatMode)
            {
                default:
                case ListRepeatModes.NoRepeat:
                    if (currentIndex >= 0)
                    {
                        currentIndex--;
                    }
                    break;
                case ListRepeatModes.RepeatAll:
                    currentIndex--;
                    if (currentIndex < 0)
                    {
                        currentIndex = 0;
                    }
                    break;

                case ListRepeatModes.RepeatItem:
                    return;
            }
        }

        private void OpenUri(Uri uri)
        {
            string extension = FileUriHelper.GetExtension(uri).ToLower();
            if (dictOfServices.ContainsKey(extension))
            {
                IOpenerService ios = dictOfServices[extension];
                IUriOpenerService iuos = ios as IUriOpenerService;
                if (iuos != null)
                {
                    iuos.Open(uri);
                }
                else
                {
                    throw new NotSupportedException(string.Format("Loading uri with extension of {0} is not supported by registered service: {1}!", extension, ios));
                }
            }
            else
            {
                throw new NotSupportedException(string.Format("Extension of {0} is not supported by any of the registered services!", extension));
            }
        }

        private List<Uri> GetSiblingUrisIfPossible(Uri uri)
        {
            List<Uri> ret = new List<Uri>();
            if (uri.IsFile)
            {
                FileInfo fI = new FileInfo(uri.OriginalString);
                string extension = FileUriHelper.GetExtension(uri).ToLower();
                if (fI.Exists)
                {
                    foreach (string str in GetSiblingExtensions(extension))
                    {
                        foreach (FileInfo file in fI.Directory.GetFiles(str))
                        {
                            ret.Add(new Uri(file.FullName));
                        }
                    }
                    return ret;
                }
            }
            ret.Add(uri);

            return ret;
        }

        private List<string> GetSiblingExtensions(string extension)
        {
            IUriOpenerService iuos = dictOfServices[extension] as IUriOpenerService;
            List<string> ret = new List<string>();
            if (iuos == null)
            {
                return ret;
            }
            foreach (string s in iuos.GetSupportedExtensions())
            {
                ret.Add("*." + s);
            }
            return ret;
        }

        #endregion

        #endregion

    }

}